package com.sihuatech.coreagent.send;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpVersion;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sihuatech.coreagent.core.communication.entity.RequestSendResult;



/**
 * 发送http请求的工具类<br>
 * 基本用法<br>
 * <source>
 * RequestSender sender = RequestSender.getInstance();<br>
 * Map<String,String> headers = new HashMap<String,String>();<br>
 * headers.put("Content-Type", "application/x-www-form-urlencoded");<br>
 * String url = "http://localhost:8080/examples/jsp/jsp2/el/basic-arithmetic.jsp?jsp_precompile";<br>
 * String result = sender.requestInvokerViaGetMethod(url, null, 30000, 3, headers, true);<br>
 * System.out.println(result);<br>
 * RequestSendResult result2 = sender.requestInvokerViaGetMethod2(url, null, 30000, 3, headers, true);<br>
 * System.out.println(result2);<br>
 * </source>
 * 
 * @author zonglin
 *
 */
public class RequestSender {

	/** The instance. */
	private static RequestSender instance = null;
	
	/** The logger. */
	private static final Log logger = LogFactory.getLog(RequestSender.class);

	/** 默认的Socket读数据超时时间. */
	private static final int DEFAULT_SOCKET_SO_TIMEOUT = 30000;

	/** 默认的Socket连接超时时间. */
	private static final int DEFAULT_SOCKET_CONNECTION_TIMEOUT = 30000;

	/** 默认的从连接池获取链接的超时时间. */
	private static final int DEFAULT_SOCKET_CONNECTION_MANAGER_TIMEOUT = 30000;
	
	private static final boolean DEFAULT_USE_HTTP1_1 = true;	

	/** 连接manager. */
	private MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();

	/** socket read数据的超时时间. */
	private int defaultTimeout = DEFAULT_SOCKET_SO_TIMEOUT;

	/** socket 建立链接的超时时间. */
	private int defaultConnectionTimeout = DEFAULT_SOCKET_CONNECTION_TIMEOUT;

	/** 从连接池获取链接的超时时间. */
	private int defaultConnectionManagerTimeout = DEFAULT_SOCKET_CONNECTION_MANAGER_TIMEOUT;

	private String crlfFlag ;
	
	/**
	 * 默认重试次数
	 */
	private int defaultRetryTimes;

	/**
	 * 单站点连接数限制
	 */
	private int maxHostConnections = MultiThreadedHttpConnectionManager.DEFAULT_MAX_HOST_CONNECTIONS;

	/**
	 * 总的连接数限制
	 */
	private int maxTotalConnections = MultiThreadedHttpConnectionManager.DEFAULT_MAX_TOTAL_CONNECTIONS;
	
	/**
	 * Instantiates a new request sender.
	 */
	public RequestSender() {
		if(instance == null) {
			instance = this;
		} else {
			if(logger.isWarnEnabled()) {
				logger.warn("you'd better use RequestSender.getInstance() method to get the Object instance");
				logger.warn("if not maybe memory leak~~");
			}
		}		
	}

	public void init() {
		mgr.getParams().setDefaultMaxConnectionsPerHost(maxHostConnections);
		mgr.getParams().setMaxTotalConnections(maxTotalConnections);
		// socket建立链接的超时时间
		if (logger.isDebugEnabled()) {
			logger.debug("socket建立链接的超时时间:" + defaultConnectionTimeout + "ms");
		}
		mgr.getParams().setConnectionTimeout(defaultConnectionTimeout);
		if("1".equals(crlfFlag)){
			Part.CRLF="\n";
		}else{
			Part.CRLF="\r\n";
		}
		Part.CRLF_BYTES = EncodingUtil.getAsciiBytes(Part.CRLF);
	}

	/**
	 * Gets the single instance of RequestSender.
	 *
	 * @return single instance of RequestSender
	 */
	public static RequestSender getInstance() {
		if (instance == null) {
			instance = new RequestSender();
			instance.init();
		}
		return instance;
	}

	/**
	 * 
	 * 初始化HttpClient连接
	 * 
	 * @param client
	 * @param timeout socket读数据的超时时间
	 * @param retryTimes 发送请求失败时的自动重试次数
	 * @param useHttp1_1 是否使用HTTP 1.1
	 * @return
	 */
	private HttpClient initHttpClient(HttpClient client, int timeout,
			int retryTimes, boolean useHttp1_1) {
		// 重试机制
		if (retryTimes <= 0) {
			retryTimes = this.defaultRetryTimes;
		}
		DefaultHttpMethodRetryHandler retryHandler = new DefaultHttpMethodRetryHandler(
				retryTimes, false);
		client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
				retryHandler);

		// 超时机制
		client.getParams().setSoTimeout(defaultTimeout);
		if (timeout > 0) {
			client.getParams().setSoTimeout(timeout);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("socket读数据的超时时间:" + client.getParams().getSoTimeout()
					+ "ms");
		}

		// 从连接池获取链接的超时时间
		if (logger.isDebugEnabled()) {
			logger.debug("设置从连接池获取链接的超时时间:" + defaultConnectionManagerTimeout
					+ "ms");
		}
		client.getParams().setConnectionManagerTimeout(
				defaultConnectionManagerTimeout);
		
		// 是否使用Http1.1
		HttpVersion version;
		if(useHttp1_1) {
			if(logger.isDebugEnabled()) {
				logger.debug("使用HTTP 1.1");
			}
			version = HttpVersion.HTTP_1_1;
		} else {
			if(logger.isDebugEnabled()) {
				logger.debug("不使用HTTP 1.1");
			}
			version = HttpVersion.HTTP_1_0;
		}
		client.getParams().setVersion(version);
		

		return client;
	}

	/**
	 * 自定义消息头参数
	 * 
	 * @param method
	 * @param header 需要额外设置的HTTP头信息
	 * @param charset 设置POST XML时的Content-Type
	 * @param followRedirects 是否自动重定向
	 * @return
	 */
	private HttpMethodBase initHttpMethod(HttpMethodBase method,
			Map<String, String> header, String charset,
			boolean followRedirects) {
		if (header == null || !header.containsKey("Content-Type")) {
			// 自定义消息头中没有设置Content-Type
			logger.warn("没有设置Content-Type，如果是Form提交请求，那么一定要设置Content-Type为application/x-www-form-urlencoded");
			method.addRequestHeader("Content-Type", "text/html; charset="
					+ charset);
		}
		if (header != null) {
			Iterator<String> it = header.keySet().iterator();
			String key = null;
			String value = null;
			while (it.hasNext()) {
				key = (String) it.next();
				value = (String) header.get(key);
				if (StringUtils.isNotBlank(key)
						&& StringUtils.isNotBlank(value)) {
					method.addRequestHeader(key, value);
				}
			}
		}
		// 设置是否自动重定向
		if(logger.isDebugEnabled()) {
			logger.debug("followRedirects="+followRedirects);
		}
		method.setFollowRedirects(followRedirects);
		return method;
	}
	
	/**
	 * Request invoker Get Method.<br />
	 * 默认使用http1.1<br />
	 * 无额外的Http消息头信息
	 *
	 * @param url 请求的URL
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @return
	 */
	public String requestInvokerViaGetMethod(String url, String charset,
			int timeout, int retryTimes) {
		if(logger.isDebugEnabled()) {
			logger.debug("默认使用Http1.1");
			logger.debug("无额外的Http消息头信息");
		}
		return this._requestInvokerViaGetMethod(url, charset, timeout, retryTimes,
				null, DEFAULT_USE_HTTP1_1);
	}
	
	/**
	 * Request invoker Get Method as InputStream
	 * 
	 * @param url
	 * @param timeout
	 * @param retryTimes
	 * @return
	 */
	public InputStream requestInvokerViaGetMethodAsStream(String url,
			int timeout, int retryTimes) {
		if (logger.isDebugEnabled()) {
			logger.debug("默认使用Http1.1");
			logger.debug("无额外的Http消息头信息");
		}
		return this._requestInvokerViaGetMethodAsStream(url, null, timeout,
				retryTimes, null, DEFAULT_USE_HTTP1_1);
	}

	/**
	 * Request invoker Get Method.<br />
	 * 默认使用http1.1
	 *
	 * @param url 请求的URL
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @param header 请求消息头参数
	 * @return
	 */
	public String requestInvokerViaGetMethod(String url, String charset,
			int timeout, int retryTimes, Map<String, String> header) {
		if(logger.isDebugEnabled()) {
			logger.debug("默认使用Http1.1");
		}
		return this._requestInvokerViaGetMethod(url, charset,
				timeout, retryTimes, header, DEFAULT_USE_HTTP1_1);
	}
	
	/**
	 * Request invoker Get Method.<br />
	 * 默认使用http1.1
	 *
	 * @param url 请求的URL
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @param header 请求消息头参数
	 * @param useHttp1_1 是否使用Http1.1
	 * @return 请求的内容
	 */
	public String requestInvokerViaGetMethod(String url, String charset,
			int timeout, int retryTimes, Map<String, String> header, boolean useHttp1_1) {
		return this._requestInvokerViaGetMethod(url, charset,
				timeout, retryTimes, header, useHttp1_1);
	}
	
	/**
	 * Request invoker Get Method.<br />
	 * 默认使用http1.1
	 *
	 * @param url 请求的URL
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @param header 请求消息头参数
	 * @param useHttp1_1 是否使用Http1.1
	 * @param followRedirects 是否需要自动重定向
	 * @return 请求的内容封装的对象 
	 * 
	 * @see RequestSendResult
	 */
	public RequestSendResult requestInvokerViaGetMethod2(String url,
			String charset, int timeout, int retryTimes,
			Map<String, String> header, boolean useHttp1_1,
			boolean followRedirects) {
		return this._requestInvokerViaGetMethod2(url, charset, timeout,
				retryTimes, header, useHttp1_1, false, followRedirects);
	}
	
	private String _requestInvokerViaGetMethod(String url, String charset,
			int timeout, int retryTimes, Map<String, String> header,
			boolean useHttp1_1) {
		boolean isText = true;
		boolean followRedirects = true;
		RequestSendResult result = this._requestInvokerViaGetMethod2(url,
				charset, timeout, retryTimes, header, useHttp1_1, isText,
				followRedirects);
		if (result.getResponseCode() == 200) {
			return result.getResponseBodyString();
		} else {
			logger.warn("错误的HTTP返回码 " + result.getResponseCode());
			return "";
		}
	}
	
	private RequestSendResult _requestInvokerViaGetMethod2(String url,
			String charset, int timeout, int retryTimes,
			Map<String, String> header, boolean useHttp1_1, boolean isText,
			boolean followRedirects) {
		HttpClient client = new HttpClient(mgr);
		initHttpClient(client, timeout, retryTimes, useHttp1_1);
		GetMethod method = new GetMethod(url);
		if (charset == null || charset.trim().equals("")) {
			logger.warn("没有设置字符集，使用默认字符集utf-8");
			charset = "utf-8";
		}
		initHttpMethod(method, header, charset, followRedirects);
		RequestSendResult result = this.sendHttpRequest(url, charset, isText,
				client, method);
		return result;
	}
	
	private InputStream _requestInvokerViaGetMethodAsStream(String url, String charset,
			int timeout, int retryTimes, Map<String, String> header, boolean useHttp1_1) {
		boolean isText = false;
		boolean followRedirects = true;
		RequestSendResult result = this._requestInvokerViaGetMethod2(url,
				charset, timeout, retryTimes, header, useHttp1_1, isText,
				followRedirects);
		if (result.getResponseCode() == 200) {
			return new ByteArrayInputStream(result.getResponseBodyStream());
		} else {
			logger.warn("错误的HTTP返回码 " + result.getResponseCode());
			return null;
		}
	}

	/**
	 * Request invoker.取得重定向的地址
	 *
	 * @param url 请求的URL
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param header 请求消息头参数
	 * @return
	 */
	public String getRedirectUrl(String url, String charset,
			Map<String, String> header) {
		if (logger.isDebugEnabled()) {
			logger.debug("使用预设的超时时间:" + defaultTimeout);
			logger.debug("使用预设的重试次数:" + defaultRetryTimes);
			logger.debug("默认使用Http1.1");
		}
		return this._getRedirectUrlViaGetMethod(url, charset, defaultTimeout,
				defaultRetryTimes, header, DEFAULT_USE_HTTP1_1);
	}
	
	/**
	 * Request invoker.取得重定向的地址
	 *
	 * @param url 请求的URL
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @param header 请求消息头参数
	 * @return
	 */
	public String getRedirectUrlViaGetMethod(String url, String charset,
			int timeout, int retryTimes, Map<String, String> header) {
		if (logger.isDebugEnabled()) {
			logger.debug("默认使用Http1.1");
		}
		return this._getRedirectUrlViaGetMethod(url, charset, timeout,
				retryTimes, header, DEFAULT_USE_HTTP1_1);
	}
	
	private String _getRedirectUrlViaGetMethod(String url, String charset,
			int timeout, int retryTimes, Map<String, String> header,
			boolean useHttp1_1) {
		boolean followRedirects = false;
		boolean isText = false;
		RequestSendResult result = this._requestInvokerViaGetMethod2(url,
				charset, timeout, retryTimes, header, useHttp1_1, isText,
				followRedirects);
		if (result.getResponseCode() >= 300 && result.getResponseCode() < 400) {
			if (result.containsHeader("location")) {
				return result.getHeaders("location").get(0);
			} else {
				logger.warn("HTTP应答消息头中没有发现 location");
				return "";
			}
		} else {
			logger.warn("错误的HTTP 重定向返回码 " + result.getResponseCode());
			return "";
		}
	}

	/**
	 * Request invoker.取得重定向的地址
	 *
	 * @param url 请求的URL
	 * @param requestBody 请求体
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @param header 请求消息头参数
	 * @return
	 */
	public String getRedirectUrlViaPostMethod(String url, String requestBody,
			String charset, int timeout, int retryTimes,
			Map<String, String> header) {
		if (logger.isDebugEnabled()) {
			logger.debug("默认使用Http1.1");
		}
		return this._getRedirectUrlViaPostMethod(url, requestBody, charset,
				timeout, retryTimes, header, DEFAULT_USE_HTTP1_1);
	}
	
	private String _getRedirectUrlViaPostMethod(String url, String requestBody,
			String charset, int timeout, int retryTimes,
			Map<String, String> header, boolean useHttp1_1) {
		RequestSendResult result = this._requestInvokerrViaPostMethod2(url,
				requestBody, charset, timeout, retryTimes, header, useHttp1_1,
				false);
		if (result.getResponseCode() >= 300 && result.getResponseCode() < 400) {
			if (result.containsHeader("location")) {
				return result.getHeaders("location").get(0);
			} else {
				logger.warn("HTTP应答消息头中没有发现 location");
				return "";
			}
		} else {
			logger.warn("错误的HTTP 重定向返回码 " + result.getResponseCode());
			return "";
		}
	}

	/**
	 * Request invoker Post Method.<br />
	 * 默认的超时时间<br />
	 * 默认的重试次数<br />
	 * 默认使用http1.1<br />
	 * 无额外的Http消息头信息
	 * 
	 * @param url 请求的URL
	 * @param requestBody 请求体
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @return
	 */
	@Deprecated
	public String requestInvoker(String url, String requestBody, String charset) {
		if (logger.isDebugEnabled()) {
			logger.debug("使用预设的超时时间:" + defaultTimeout);
			logger.debug("使用预设的重试次数:" + defaultRetryTimes);
			logger.debug("默认使用Http1.1");
			logger.debug("无额外的Http消息头信息");
		}
		return this._requestInvokerrViaPostMethod(url, requestBody, charset,
				defaultTimeout, defaultRetryTimes, null, DEFAULT_USE_HTTP1_1);
	}	

	/**
	 * Request invoker Post Method.<br />
	 * 默认使用http1.1
	 *
	 * @param url 请求的URL
	 * @param requestBody 请求体
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @param header 请求消息头参数
	 * @return
	 */
	public String requestInvokerrViaPostMethod(String url, String requestBody,
			String charset, int timeout, int retryTimes,
			Map<String, String> header) {
		if(logger.isDebugEnabled()) {
			logger.debug("默认使用Http1.1");
		}
		return this._requestInvokerrViaPostMethod(url,requestBody,
				charset,timeout,retryTimes,header,DEFAULT_USE_HTTP1_1);
	}
	
	/**
	 * Request invoker Post Method.<br />
	 *
	 * @param url 请求的URL
	 * @param requestBody 请求体
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @param header 请求消息头参数
	 * @param useHttp1_1 是否使用Http1.1
	 * @return
	 */	
	public String requestInvokerrViaPostMethod(String url, String requestBody,
			String charset, int timeout, int retryTimes,
			Map<String, String> header,String head, boolean useHttp1_1) {
		return this._requestInvokerrViaPostMethod(url,requestBody,
				charset,timeout,retryTimes,header,useHttp1_1);
	}	
	
	public RequestSendResult requestInvokerrViaPostMethod2(String url,
			String requestBody, String charset, int timeout, int retryTimes,
			Map<String, String> header, boolean useHttp1_1) {
		boolean isText = false;
		return this._requestInvokerrViaPostMethod2(url, requestBody, charset,
				timeout, retryTimes, header, useHttp1_1, isText);
	}
	
	public RequestSendResult requestInvokerrViaPostMethod3(String url,
			byte[] requestBody, int timeout, int retryTimes,
			Map<String, String> header, boolean useHttp1_1) {
		boolean isText = false;
		return this._requestInvokerrViaPostMethod3(url, requestBody,null,
				timeout, retryTimes, header, useHttp1_1, isText);
	}

	public RequestSendResult requestInvokerrViaPostMethod3(String url,
			HttpServletRequest request,Map<String, String> header, int timeout, int retryTimes, boolean useHttp1_1) {
		boolean isText = false;
		if(header==null){
			header=new HashMap<String, String>();
		}
		Enumeration headerNames = request.getHeaderNames();
		if(headerNames!=null){
		    while (headerNames.hasMoreElements()) {
			       String key = (String) headerNames.nextElement();
			       String value = request.getHeader(key);
			       header.put(key, value);
			 }
		}

		try {
			return this._requestInvokerrViaPostMethod3(url, null,request.getInputStream(),
					timeout, retryTimes, header, useHttp1_1, isText);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Request invoker Post Method.<br />
	 * 默认的超时时间<br />
	 * 默认的重试次数<br />
	 * 默认使用http1.1
	 *
	 * @param url 请求的URL
	 * @param requestBody 请求体
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param header 请求消息头参数
	 * @return
	 */
	@Deprecated
	public String requestInvoker(String url, String requestBody,
			String charset, Map<String, String> header) {
		if(logger.isDebugEnabled()) {
			logger.debug("使用预设的超时时间:"+defaultTimeout);
			logger.debug("使用预设的重试次数:"+defaultRetryTimes);
			logger.debug("默认使用Http1.1");
		}
		return this._requestInvokerrViaPostMethod(url, requestBody, charset,
				defaultTimeout, defaultRetryTimes, header, DEFAULT_USE_HTTP1_1);
	}

	/**
	 * Request invoker Post Method.<br />
	 * 默认使用http1.1<br />
	 * 无额外的Http消息头信息
	 * 
	 * @param url 请求的URL
	 * @param requestBody 请求体
	 * @param charset 字符集,如果NULL,默认为UTF-8
	 * @param timeout 连接超时时间
	 * @param retryTimes 重试次数
	 * @return
	 */
	public String requestInvokerrViaPostMethod(String url, String requestBody,
			String charset, int timeout, int retryTimes) {
		if(logger.isDebugEnabled()) {
			logger.debug("默认使用Http1.1");
			logger.debug("无额外的Http消息头信息");
		}
		return this._requestInvokerrViaPostMethod(url, requestBody, charset,
				timeout, retryTimes, null, DEFAULT_USE_HTTP1_1);
	}
	
	public String requestMultipartPostMethod(String url, Part[] parts,
			String charset, int timeout, int retryTimes) {
		if(logger.isDebugEnabled()) {
			logger.debug("默认使用Http1.1");
			logger.debug("无额外的Http消息头信息");
		}
		boolean isText = true;
		boolean followRedirects = false;
		HttpClient client = new HttpClient(mgr);
		initHttpClient(client, timeout, retryTimes, true);

		PostMethod method = new PostMethod(url);
		if (charset == null || charset.trim().equals("")) {
			charset = "utf-8";
		}
		
		RequestSendResult result = new RequestSendResult();
		RequestEntity requestEntity = null;
		MultipartRequestEntity entity = new MultipartRequestEntity(parts, new HttpMethodParams());
		method.setRequestHeader("Connection", "close");
		method.setRequestEntity(entity);  
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("向" + url + "发送消息");
			}
			int responseCode = client.executeMethod(method);
			result.setResponseCode(responseCode);			
			if (logger.isDebugEnabled()) {
				logger.debug("http response code=" + responseCode);
			}
			
			if (responseCode >= 300 && responseCode < 400) { 
				// 重定向不需要获取responseBody
			} else {
				// 其他需要获取responseBody
				byte[] responseBodyStream = IOUtils.toByteArray(method
						.getResponseBodyAsStream());
				result.setResponseBodyStream(responseBodyStream);
				if(logger.isDebugEnabled() && responseBodyStream != null) {
					logger.debug("length="+responseBodyStream.length);
				}
				if (isText) {
					if(logger.isDebugEnabled()) {
						logger.debug("需要转换为String");
					}
					if(responseBodyStream == null) {
						logger.warn("responseBodyStream is null");
					} else {
						String responseBodyString = new String(responseBodyStream,
								charset);
						result.setResponseBodyString(responseBodyString);
						if (logger.isDebugEnabled()) {
							logger.debug("回执消息为\n" + responseBodyString);
						}
					}					
				} else {
					if(logger.isDebugEnabled()) {
						logger.debug("不需要转换为String");
					}
				}
			}			
			
		} catch (ConnectException ce) {
			logger.error("无法连接到指定地址",ce);
		} catch (Exception e) {
			logger.error("其他错误",e);
		} finally {
			method.releaseConnection();
		}		
		

		if (result.getResponseCode() == 200) {
			return result.getResponseBodyString();
		} else {
			logger.warn("错误的HTTP返回码 " + result.getResponseCode());
			return "";
		}
	}
	
	private String _requestInvokerrViaPostMethod(String url,
			String requestBody, String charset, int timeout, int retryTimes,
			Map<String, String> header, boolean useHttp1_1) {
		boolean isText = true;
		RequestSendResult result = this._requestInvokerrViaPostMethod2(url,
				requestBody, charset, timeout, retryTimes, header, useHttp1_1,
				isText);
		if (result.getResponseCode() == 200) {
			return result.getResponseBodyString();
		} else {
			logger.warn("错误的HTTP返回码 " + result.getResponseCode());
			return "";
		}
	}
	
	private RequestSendResult _requestInvokerrViaPostMethod2(String url,
			String requestBody, String charset, int timeout, int retryTimes,
			Map<String, String> header, boolean useHttp1_1, boolean isText) {
		// Post Method 不支持自动重定向
		boolean followRedirects = false;
		HttpClient client = new HttpClient(mgr);
		initHttpClient(client, timeout, retryTimes, useHttp1_1);

		PostMethod method = new PostMethod(url);
		if (charset == null || charset.trim().equals("")) {
			charset = "utf-8";
		}
		initHttpMethod(method, header, charset, followRedirects);
		RequestSendResult result = new RequestSendResult();
		RequestEntity requestEntity = null;
		try{
			requestEntity = new StringRequestEntity(requestBody,null,charset);
			method.setRequestEntity(requestEntity);
			if (logger.isDebugEnabled()) {
				logger.info("请求消息为\n" + requestBody);
			}
			result = this.sendHttpRequest(url, charset, isText,
					client, method);
		}catch(UnsupportedEncodingException e){
			logger.error("构造StringRequestEntity出错",e);
		}		
		
		return result;
	}
	
	private RequestSendResult _requestInvokerrViaPostMethod3(String url,
			byte[]  requestBody, InputStream inputStream,int timeout, int retryTimes,
			Map<String, String> header, boolean useHttp1_1, boolean isText) {
		// Post Method 不支持自动重定向
		boolean followRedirects = false;
		HttpClient client = new HttpClient(mgr);
		initHttpClient(client, timeout, retryTimes, useHttp1_1);
		PostMethod method = new PostMethod(url);
		initHttpMethod(method, header, null, followRedirects);
		RequestSendResult result = new RequestSendResult();
		//requestEntity = new StringRequestEntity(requestBody,null,null);
		//method.setRequestEntity(requestEntity);
		if(inputStream==null){
			method.setRequestBody(inputStream);
		}else if(requestBody!=null){
			method.setRequestBody(new ByteArrayInputStream(requestBody));
		}
		
		if (logger.isDebugEnabled()) {
			logger.debug("请求消息为\n" + requestBody);
		}
		result = this.sendHttpRequest(url, null, isText,
				client, method);		
		
		return result;
	}
	private RequestSendResult sendHttpRequest(String url, String charset,
			boolean isText, HttpClient client, HttpMethodBase method) {
		RequestSendResult result = new RequestSendResult();

		try {
			if (logger.isDebugEnabled()) {
				logger.debug("向" + url + "发送消息");
			}
			int responseCode = client.executeMethod(method);
			result.setResponseCode(responseCode);			
			if (logger.isDebugEnabled()) {
				logger.debug("http response code=" + responseCode);
			}
			
			if (responseCode >= 300 && responseCode < 400) { 
				// 重定向不需要获取responseBody
			} else {
				// 其他需要获取responseBody
				byte[] responseBodyStream = IOUtils.toByteArray(method
						.getResponseBodyAsStream());
				result.setResponseBodyStream(responseBodyStream);
				if(logger.isDebugEnabled() && responseBodyStream != null) {
					logger.debug("length="+responseBodyStream.length);
				}
				if (isText) {
					if(logger.isDebugEnabled()) {
						logger.debug("需要转换为String");
					}
					if(responseBodyStream == null) {
						logger.warn("responseBodyStream is null");
					} else {
						String responseBodyString = new String(responseBodyStream,
								charset);
						result.setResponseBodyString(responseBodyString);
						if (logger.isDebugEnabled()) {
							logger.debug("回执消息为\n" + responseBodyString);
						}
					}					
				} else {
					if(logger.isDebugEnabled()) {
						logger.debug("不需要转换为String");
					}
				}
			}
			
			Header[] responseHeaders = method.getResponseHeaders();
			for(Header responseHeader : responseHeaders) {
				result.addHeader(responseHeader.getName(), responseHeader.getValue());
			}			
			
		} catch (ConnectException ce) {
			logger.error("无法连接到指定地址",ce);
		} catch (Exception e) {
			logger.error("其他错误",e);
		} finally {
			method.releaseConnection();
		}
		
		return result;
	}

	public void setDefaultTimeout(int defaultTimeout) {
		this.defaultTimeout = defaultTimeout;
	}

	public void setDefaultRetryTimes(int defaultRetryTimes) {
		this.defaultRetryTimes = defaultRetryTimes;
	}

	public void setMaxHostConnections(int maxHostConnections) {
		this.maxHostConnections = maxHostConnections;
	}

	public void setMaxTotalConnections(int maxTotalConnections) {
		this.maxTotalConnections = maxTotalConnections;
	}

	public void setDefaultConnectionTimeout(int defaultConnectionTimeout) {
		this.defaultConnectionTimeout = defaultConnectionTimeout;
	}

	public void setDefaultConnectionManagerTimeout(
			int defaultConnectionManagerTimeout) {
		this.defaultConnectionManagerTimeout = defaultConnectionManagerTimeout;
	}
	public String getCrlfFlag() {
		return crlfFlag;
	}

	public void setCrlfFlag(String crlfFlag) {
		this.crlfFlag = crlfFlag;
	}
}
